package com.travel.utils;

import java.util.*;

// 用户行为评分矩阵类
class Recommendation {

    // 用户-商品评分矩阵 (用户ID -> 商品ID -> 隐式评分)
    private Map<Integer, Map<Integer, Integer>> userItemRatings;

    public Recommendation() {
        this.userItemRatings = new HashMap<>();
    }

    // 向矩阵中添加用户行为评分
    public void addBehavior(int userId, int itemId, String behavior) {
        // 获取该用户的评分记录
        userItemRatings.putIfAbsent(userId, new HashMap<>());
        Map<Integer, Integer> userRatings = userItemRatings.get(userId);

        // 根据行为类型分配评分
        int score = 0;
        switch (behavior) {
            case "click":
                score = 1; // 点击
                break;
            case "buy":
                score = 5; // 购买
                break;
            case "favorite":
                score = 4; // 收藏
                break;
            case "comment":
                score = 3; // 评论
                break;
            default:
                break;
        }
        userRatings.put(itemId, score); // 为该商品赋予评分
    }

    // 获取用户对特定商品的隐式评分
    public Integer getRating(int userId, int itemId) {
        return userItemRatings.containsKey(userId) ? userItemRatings.get(userId).get(itemId) : null;
    }

    // 获取所有用户-商品评分矩阵
    public Map<Integer, Map<Integer, Integer>> getUserItemRatings() {
        return userItemRatings;
    }

    // 计算用户之间的余弦相似度
    public double getUserSimilarity(int userId1, int userId2) {
        Map<Integer, Integer> user1Ratings = userItemRatings.get(userId1);
        Map<Integer, Integer> user2Ratings = userItemRatings.get(userId2);

        if (user1Ratings == null || user2Ratings == null) {
            return 0;  // 如果没有评分记录，返回0
        }

        return Similarity.cosineSimilarity(user1Ratings, user2Ratings);
    }

    // 基于用户的协同过滤推荐商品
    public List<Integer> recommendItems(int userId, int topN) {
        Map<Integer, Double> userSimilarities = new HashMap<>();

        // 计算目标用户与其他用户的相似度
        for (int otherUserId : userItemRatings.keySet()) {
            if (otherUserId != userId) {
                double similarity = getUserSimilarity(userId, otherUserId);
                userSimilarities.put(otherUserId, similarity);
            }
        }

        // 按相似度从高到低排序，选择最相似的N个用户
        List<Map.Entry<Integer, Double>> sortedUsers = new ArrayList<>(userSimilarities.entrySet());
        sortedUsers.sort((a, b) -> b.getValue().compareTo(a.getValue()));

        Set<Integer> recommendedItems = new HashSet<>();
        for (Map.Entry<Integer, Double> entry : sortedUsers.subList(0, Math.min(topN, sortedUsers.size()))) {
            int similarUserId = entry.getKey();
            Map<Integer, Integer> similarUserRatings = userItemRatings.get(similarUserId);

            for (Map.Entry<Integer, Integer> rating : similarUserRatings.entrySet()) {
                int itemId = rating.getKey();
                int score = rating.getValue();

                // 如果目标用户没有评分该商品，则将其加入推荐列表
                if (!userItemRatings.get(userId).containsKey(itemId)) {
                    recommendedItems.add(itemId);
                }
            }
        }

        return new ArrayList<>(recommendedItems);
    }
}

// 计算相似度的类
class Similarity {

    // 计算两个用户之间的余弦相似度
    public static double cosineSimilarity(Map<Integer, Integer> user1Ratings, Map<Integer, Integer> user2Ratings) {
        double dotProduct = 0;
        double user1Magnitude = 0;
        double user2Magnitude = 0;

        for (int itemId : user1Ratings.keySet()) {
            if (user2Ratings.containsKey(itemId)) {
                int rating1 = user1Ratings.get(itemId);
                int rating2 = user2Ratings.get(itemId);
                dotProduct += rating1 * rating2;
                user1Magnitude += Math.pow(rating1, 2);
                user2Magnitude += Math.pow(rating2, 2);
            }
        }

        if (user1Magnitude == 0 || user2Magnitude == 0) {
            return 0; // 如果没有共同评分的商品，则相似度为0
        }

        return dotProduct / (Math.sqrt(user1Magnitude) * Math.sqrt(user2Magnitude));
    }
}

// 主方法/应用入口（可以是服务类/控制器）
/*public class Main {

    public static void main(String[] args) {
        Recommendation recommendation = new Recommendation();

        // 模拟添加用户行为数据
        recommendation.addBehavior(1, 101, "buy");       // 用户1购买了商品101
        recommendation.addBehavior(1, 102, "click");     // 用户1点击了商品102
        recommendation.addBehavior(2, 101, "favorite");  // 用户2收藏了商品101
        recommendation.addBehavior(2, 103, "buy");       // 用户2购买了商品103

        // 获取推荐
        List<Integer> recommendedItems = recommendation.recommendItems(1, 3);

        // 输出推荐商品
        System.out.println("推荐商品ID: " + recommendedItems);
    }
}*/
